////////////////////////////////////////////////////////////////////////////////
// Filename: sprite.cpp
////////////////////////////////////////////////////////////////////////////////
#include "sprite.hpp"

Sprite::Sprite() {
	m_vertexBuffer = NULL;
	m_indexBuffer = NULL;
	m_texture = NULL;
	m_position = NULL;
}

Sprite::~Sprite() {

}

bool Sprite::Initialize(Vector2D* position, Graphics* graphics, WCHAR* filename, bool useAlpha) {
	miv::IRenderble::Initialize();

	bool result;

	m_position = position;
	m_alphaEnabled = useAlpha;

	result = LoadTexture(graphics->GetDirect3D()->GetDevice(), filename);
	if (!result) {
		return false;
	}

	result = InitializeBuffers(graphics->GetDirect3D()->GetDevice());
	if (!result) {
		return false;
	}

	return true;
}

bool Sprite::Initialize(Vector2D* position, Graphics* graphics, WCHAR* filename) {
	bool result;

	result = Initialize(position, graphics, filename, false);
	if (!result) {
		return false;
	}

	return true;
}

void Sprite::Shutdown() {
	ReleaseTexture();

	ShutdownBuffers();
}

void Sprite::Draw(Graphics* graphics) {
	DrawBuffers(graphics);
}

void Sprite::SetActive(ID3D11DeviceContext* deviceContext) {
	unsigned int stride;
	unsigned int offset;

	stride = sizeof(VertexType::PositionTexture);
	offset = 0;

	deviceContext->IASetVertexBuffers(0, 1, &m_vertexBuffer, &stride, &offset);
	deviceContext->IASetIndexBuffer(m_indexBuffer, DXGI_FORMAT_R32_UINT, 0);
	deviceContext->IASetPrimitiveTopology(D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST);
}

int Sprite::GetVertexCount() {
	return m_vertexCount;
}

int Sprite::GetIndexCount() {
	return m_indexCount;
}

Vector2D* Sprite::GetPosition() {
	return m_position;
}

ID3D11ShaderResourceView* Sprite::GetTexture() {
	return m_texture->GetTexture();
}

bool Sprite::InitializeBuffers(ID3D11Device* device) {
		VertexType::PositionTexture* vertices;
		unsigned long* indices;
		D3D11_BUFFER_DESC vertexBufferDesc, indexBufferDesc;
		D3D11_SUBRESOURCE_DATA vertexData, indexData;
		HRESULT result;

		m_vertexCount = 6;
		m_indexCount = 6;

		vertices = new VertexType::PositionTexture[m_vertexCount];
		if (!vertices) {
			return false;
		}

		indices = new unsigned long[m_indexCount];
		if (!indices) {
			return false;
		}

		float width = ((float)m_texture->GetWidth()) / 2.0f;
		float height = ((float)m_texture->GetHeight()) / 2.0f;

		vertices[0].position = D3DXVECTOR3(m_position->GetX() - width, m_position->GetY() - height, 0.0f);
		vertices[0].texture = D3DXVECTOR2(0.0f, 1.0f);

		vertices[1].position = D3DXVECTOR3(m_position->GetX() - width, m_position->GetY() + height, 0.0f);
		vertices[1].texture = D3DXVECTOR2(0.0f, 0.0f);

		vertices[2].position = D3DXVECTOR3(m_position->GetX() + width, m_position->GetY() + height, 0.0f);
		vertices[2].texture = D3DXVECTOR2(1.0f, 0.0f);

		vertices[3].position = D3DXVECTOR3(m_position->GetX() - width, m_position->GetY() - height, 0.0f);
		vertices[3].texture = D3DXVECTOR2(-1.0f, 0.0f);

		vertices[4].position = D3DXVECTOR3(m_position->GetX() + width, m_position->GetY() + height, 0.0f);
		vertices[4].texture = D3DXVECTOR2(0.0f, -1.0f);

		vertices[5].position = D3DXVECTOR3(m_position->GetX() + width, m_position->GetY() - height, 0.0f);
		vertices[5].texture = D3DXVECTOR2(0.0f, 0.0f);

		indices[0] = 0;
		indices[1] = 1;
		indices[2] = 2;
		indices[3] = 3;
		indices[4] = 4;
		indices[5] = 5;

		vertexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
		vertexBufferDesc.ByteWidth = sizeof(VertexType::PositionTexture) * m_vertexCount;
		vertexBufferDesc.BindFlags = D3D11_BIND_VERTEX_BUFFER;
		vertexBufferDesc.CPUAccessFlags = 0;
		vertexBufferDesc.MiscFlags = 0;
		vertexBufferDesc.StructureByteStride = 0;

		vertexData.pSysMem = vertices;
		vertexData.SysMemPitch = 0;
		vertexData.SysMemSlicePitch = 0;

		result = device->CreateBuffer(&vertexBufferDesc, &vertexData, &m_vertexBuffer);
		if (FAILED(result)) {
			return false;
		}

		indexBufferDesc.Usage = D3D11_USAGE_DEFAULT;
		indexBufferDesc.ByteWidth = sizeof(unsigned long) * m_indexCount;
		indexBufferDesc.BindFlags = D3D11_BIND_INDEX_BUFFER;
		indexBufferDesc.CPUAccessFlags = 0;
		indexBufferDesc.MiscFlags = 0;
		indexBufferDesc.StructureByteStride = 0;

		indexData.pSysMem = indices;

		result = device->CreateBuffer(&indexBufferDesc, &indexData, &m_indexBuffer);
		if (FAILED(result)) {
			return false;
		}

		delete[] vertices;
		vertices = NULL;
		delete[] indices;
		indices = NULL;

		return true;
}

void Sprite::ShutdownBuffers() {
	if (m_indexBuffer) {
		m_indexBuffer->Release();
		m_indexBuffer = NULL;
	}

	if (m_vertexBuffer) {
		m_vertexBuffer->Release();
		m_vertexBuffer = NULL;
	}
}

void Sprite::DrawBuffers(Graphics* graphics) {
	graphics->m_renderQueue->push(this);
}

bool Sprite::LoadTexture(ID3D11Device* device, WCHAR* filename) {
	bool result;

	m_texture = new Texture2D;
	if (!m_texture) {
		return false;
	}

	result = m_texture->Initialize(device, filename);
	if (!result) {
		return false;
	}

	return true;
}

void Sprite::ReleaseTexture() {
	if (m_texture) {
		m_texture->Shutdown();
		delete m_texture;
		m_texture = NULL;
	}
}

bool Sprite::IsAlphaEnabled() {
	return m_alphaEnabled;
}
